package com.pingan.haofang.searchcloud.web.index.controller;

import com.google.common.collect.Lists;
import com.pingan.haofang.framework.common.utils.UUIDUtils;
import com.pingan.haofang.searchcloud.common.constants.QueryOptimizeEnum;
import com.pingan.haofang.searchcloud.common.constants.WebConstants;
import com.pingan.haofang.searchcloud.index.dto.IndexInfoQueryResult;
import com.pingan.haofang.searchcloud.index.service.IndexService;
import com.pingan.haofang.searchcloud.metadata.dto.MetadataFieldQueryResult;
import com.pingan.haofang.searchcloud.user.service.SearchProjectService;
import com.pingan.haofang.searchcloud.web.index.vo.FullRpcIndexDataSourceVO;
import com.pingan.haofang.searchcloud.web.index.vo.IncDataSourceVO;
import com.pingan.haofang.searchcloud.web.index.vo.example.FullImportRpcRequestParam;
import com.pingan.haofang.searchcloud.web.index.vo.example.FullImportRpcResultExample;
import com.pingan.haofang.searchcloud.web.index.vo.example.IncRpcRequestParam;
import com.pingan.haofang.searchcloud.web.index.vo.example.RpcExampleRequest;
import com.pingan.haofang.searchcloud.web.index.vo.example.RpcExampleResponse;
import com.pingan.haofang.searchcloud.web.index.vo.example.RpcExampleResponseResult;
import com.pingan.haofang.searchcloud.web.index.vo.example.RpcExampleVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.ValidationException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * IndexDatasource 请求示例接口
 *
 * @author zhangbi617
 * @date 03/05/2017
 */
@RestController
@RequestMapping(value = WebConstants.WEB_PREFIX + "/datasource/example")
@Api(tags = "Index.Datasource", description = "索引数据源示例接口")
public class IndexDatasourceExampleController {

    @Autowired
    private IndexService indexService;

    @Autowired
    private SearchProjectService searchProjectService;


    @ApiOperation("全量导入的数据接口示例")
    @PostMapping("fullRpc/{indexId}")
    public RpcExampleVo<List<FullImportRpcRequestParam>, FullImportRpcResultExample> fullRpcDatasourceExample(
            @ApiParam(value = "索引ID") @PathVariable("indexId") Long indexId,
            @ApiParam(name = "payload", value = "payload")
            @Valid @RequestBody FullRpcIndexDataSourceVO fullRpcIndexDataSourceVO, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            Optional<String> first = bindingResult.getAllErrors().stream().map(ObjectError::getDefaultMessage).findFirst();
            throw new ValidationException(first.orElse("field valid error"));
        }

        RpcExampleVo result = new RpcExampleVo();
        result.setUrl(fullRpcIndexDataSourceVO.getRpcUrl());

        // 请求
        FullImportRpcRequestParam param = new FullImportRpcRequestParam();
        param.setPageNo(1);
        param.setPageSize(fullRpcIndexDataSourceVO.getPageSize());
        param.setBefore((int) (System.currentTimeMillis() / 1000));
        if (QueryOptimizeEnum.ENABLE.code() == fullRpcIndexDataSourceVO.getQueryOptimize()) {
            param.setLastMaxId(123L);
        }
        result.setRequest(buildRpcExampleRequest(param, fullRpcIndexDataSourceVO.getRpcMethod()));

        // 响应示例
        IndexInfoQueryResult indexInfoQueryResult = indexService.queryById(indexId);

        FullImportRpcResultExample response = new FullImportRpcResultExample();
        response.setDatas(generateExampleDatas(indexInfoQueryResult.getFields(), 5));
        response.setTotal(10000);
        result.setResponse(buildRpcExampleResponse(response, "成功", 0));

        return result;
    }

    @ApiOperation("增量推送到搜索平台接口示例")
    @PostMapping("incRpc/{indexId}")
    public RpcExampleVo<List<IncRpcRequestParam>, FullImportRpcResultExample> incRpcDatasourceExample(
            @ApiParam(value = "索引ID") @PathVariable("indexId") Long indexId,
            @ApiParam(name = "payload", value = "payload") @Valid @RequestBody IncDataSourceVO param, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            Optional<String> first = bindingResult.getAllErrors().stream().map(ObjectError::getDefaultMessage).findFirst();
            throw new ValidationException(first.orElse("field valid error"));
        }
        IndexInfoQueryResult indexInfoQueryResult = indexService.queryById(indexId);

        RpcExampleVo rpcExampleVo = new RpcExampleVo();
        rpcExampleVo.setUrl(param.getRpcUrl());

        Map incRpcRequestParam = new HashMap();
        incRpcRequestParam.put("versionFrom",0L);
        incRpcRequestParam.put("versionTo",System.currentTimeMillis());
        incRpcRequestParam.put("pageNo",1);
        incRpcRequestParam.put("pageSize",param.getPageSize());
        rpcExampleVo.setRequest(buildRpcExampleRequest(incRpcRequestParam, param.getRpcMethod()));


        FullImportRpcResultExample response = new FullImportRpcResultExample();
        response.setDatas(generateExampleDatas(indexInfoQueryResult.getFields(), 5));
        response.setTotal(10000);
        rpcExampleVo.setResponse(buildRpcExampleResponse(response, "成功", 0));

        return rpcExampleVo;
    }


    @ApiOperation("增量回调反查接口示例")
    @PostMapping("incRpcCallback/{indexId}")
    public RpcExampleVo<List<IncRpcRequestParam>, FullImportRpcResultExample> incRpcCallbackDatasourceExample(
            @ApiParam(value = "索引ID") @PathVariable("indexId") Long indexId,
            @ApiParam(name = "payload", value = "payload")
            @Valid @RequestBody IncDataSourceVO param, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            Optional<String> first = bindingResult.getAllErrors().stream().map(ObjectError::getDefaultMessage).findFirst();
            throw new ValidationException(first.orElse("field valid error"));
        }

        IndexInfoQueryResult indexInfoQueryResult = indexService.queryById(indexId);
        RpcExampleVo rpcExampleVo = new RpcExampleVo();
        rpcExampleVo.setUrl(param.getRpcUrl());

        Map incRpcRequestParam = new HashMap();
        incRpcRequestParam.put("versionFrom",0);
        incRpcRequestParam.put("pageNo",1);
        incRpcRequestParam.put("versionTo",System.currentTimeMillis());
        incRpcRequestParam.put("pageSize",param.getPageSize());
        rpcExampleVo.setRequest(buildRpcExampleRequest(incRpcRequestParam, param.getRpcMethod()));

        FullImportRpcResultExample response = new FullImportRpcResultExample();
        response.setDatas(generateExampleDatas(indexInfoQueryResult.getFields(), 5));
        response.setTotal(10000);
        rpcExampleVo.setResponse(buildRpcExampleResponse(response, "成功", 0));

        return rpcExampleVo;
    }

    /**
     * 生成示例
     *
     * @param fields
     * @param rows
     * @return
     */
    private List<Map<String, Object>> generateExampleDatas(List<MetadataFieldQueryResult> fields, int rows) {
        List<Map<String, Object>> result = new ArrayList<>();

        for (int i = 0; i < rows; i++) {
            Map<String, Object> row = new HashMap<>(fields.size());
            for (MetadataFieldQueryResult field : fields) {
                String fieldName = field.getFieldName();
                if (field.isMultiValued()) {
                    List<String> values = Lists.newArrayList(fieldName + "_value1", fieldName + "_value2");
                    row.put(fieldName, values);
                } else {
                    row.put(fieldName, fieldName + "_value");
                }
            }
            result.add(row);
        }
        return result;
    }

    /**
     * 构建请求
     *
     * @param params
     * @return
     */
    private <T> RpcExampleRequest buildRpcExampleRequest(T params, String method) {
        RpcExampleRequest rpcExampleRequest = new RpcExampleRequest();
        rpcExampleRequest.setId(UUIDUtils.getUUID());
        rpcExampleRequest.setJsonrpc("2.0");
        rpcExampleRequest.setMethod(method);
        rpcExampleRequest.setParams(Lists.newArrayList(params));
        return rpcExampleRequest;
    }

    /**
     * 构建响应
     *
     * @param data 数据
     * @return
     */
    private <T> RpcExampleResponse buildRpcExampleResponse(T data, String message, int code) {
        RpcExampleResponse rpcExampleResponse = new RpcExampleResponse();
        rpcExampleResponse.setId(UUIDUtils.getUUID());
        rpcExampleResponse.setJsonrpc("2.0");
        RpcExampleResponseResult<T> resultExample = new RpcExampleResponseResult<T>();
        resultExample.setErrorCode(code);
        resultExample.setErrorMessage(message);
        resultExample.setDatas(Lists.newArrayList(data));
        rpcExampleResponse.setResult(resultExample);
        return rpcExampleResponse;
    }
}
